﻿using System;
using System.Windows.Input;
using System.Diagnostics;

namespace SimpleDbBrowser
{
    /// <summary>
    /// RelayCommand exists to ease implementation linking of commands to 
    /// viewmodels
    /// </summary>
    /// <remarks>
    /// This code was taken from http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
    /// </remarks>
    public class RelayCommand : ICommand
    {
        private readonly Predicate<object> canExec;
        private readonly Action<object> exec;

        /// <summary>
        /// Initializes a new instance of the RelayCommand class.
        /// </summary>
        /// <param name="execute">
        /// A delegate responsible for executing this command.
        /// </param>
        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
            return;
        }

        /// <summary>
        /// Initializes a new instance of the RelayCommand class.
        /// </summary>
        /// <param name="execute">
        /// A delegate responsible for executing this command.
        /// </param>
        /// <param name="canExecute">
        /// A delegate responsible for determining whether this command can be executed.
        /// </param>
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null) throw new ArgumentNullException("execute");

            this.exec = execute;
            this.canExec = canExecute ?? (o => true);

            return;
        }

        #region ICommand Members

        /// <summary>
        /// Defines the method that determines whether the command can execute in its current state
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require data to be passed, this object can be set to null.
        /// </param>
        /// <returns>
        /// True if the command can be executed, otherwise false.
        /// </returns>
        [DebuggerNonUserCode]
        public bool CanExecute(object parameter)
        {
            return this.canExec(parameter);
        }

        /// <summary>
        /// Occurs when changes occur that affect whether or not the command should execute.
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require data to 
        /// be passed, this object can be set to null.
        /// </param>
        [DebuggerNonUserCode]
        public void Execute(object parameter)
        {
            this.exec(parameter);

            return;
        }

        #endregion
    }
}